// Package controller @author dingrui @since 2021/11/27
package controller

import (
	"fmt"
	"log"
	"strings"

	"github.com/kataras/iris/v12"
	"github.com/kataras/iris/v12/hero"

	"github.com/bannirui/mini-prize/common"
	"github.com/bannirui/mini-prize/dal/model"
	"github.com/bannirui/mini-prize/dal/service"
	"github.com/bannirui/mini-prize/datasource"
	"github.com/bannirui/mini-prize/web/entity/vo"
	"github.com/bannirui/mini-prize/web/util/response"
)

func AdminCouponRouter(party iris.Party) {
	var (
		party_     = party.Party("/admin-coupon")
		controller = AdminCouponController{}
	)
	party_.Get("/", hero.Handler(controller.Get))
	party_.Post("/", hero.Handler(controller.PostImport))
	party_.Delete("/", hero.Handler(controller.GetDelete))
	party_.Get("/reset", hero.Handler(controller.GetReset))
	party_.Get("/recache", hero.Handler(controller.GetRecache))
}

type AdminCouponController struct {
}

//
//  Get
//  @Description:
//                GET http://localhost:8080/api/mini-prize/admin-coupon/?giftId=1&page=1&size=10
//  @receiver c
//  @param ctx
//
func (c *AdminCouponController) Get(ctx iris.Context) {
	var (
		giftId   int
		page     int
		size     int
		total    int      // response中的属性
		dbCnt    int      // 数据库中记录数量
		cacheCnt int      // 缓存中记录数量
		prevPage int = -1 // -1表示没有前一页
		nextPage int = -1 // -1表示没有下一页
		dataList []model.Coupon
		data     model.Coupon
		rs       interface{} // redis的响应
		err      error
	)
	giftId = ctx.URLParamIntDefault("giftId", 0)
	page = ctx.URLParamIntDefault("page", 1)
	size = ctx.URLParamIntDefault("size", 10)
	// 数据列表
	if giftId > 0 {
		// db中查询
		dataList = service.G_couponService.Search(giftId)
		// 统计db中查询到的有效记录数量
		if len(dataList) > 0 {
			for _, data = range dataList {
				if data.Status == 0 {
					dbCnt++
				}
			}
		}
		// 统计缓存中的key值数量
		if rs, err = datasource.G_redis.Do("SCARD", fmt.Sprintf("gift_coupon_%d", giftId)); err != nil {
			goto ERR
		}
		// 格式转换
		cacheCnt = int(common.GetInt64(rs, 0))
	} else {
		// 查询出数据库中所有的优惠券
		dataList = service.G_couponService.GetAll(page, size)
	}
	total = (page - 1) + len(dataList)
	// 数据总数
	if len(dataList) >= size {
		if giftId > 0 {
			total = int(service.G_couponService.CountByGift(giftId))
		} else {
			total = int(service.G_couponService.CountAll())
		}
		nextPage = page + 1
	}
	if page > 1 {
		prevPage = page - 1
	}
	// 构造响应体
	response.Ok(ctx, response.CODE_OK, &vo.PageCouponVO{
		GiftId:   giftId,
		DataList: dataList,
		Total:    total,
		PrevPage: prevPage,
		NextPage: nextPage,
		DBCnt:    dbCnt,
		CacheCnt: cacheCnt,
	})
	return
ERR:
	log.Println("[-] ERROR: ", err)
	response.InternalServerError(ctx, response.CODE_FAILUR)
	return
}

//
//  PostImport
//  @Description:
//                Post http://localhost:8080/api/mini-prize/admin-coupon/?giftId=1
//  @receiver c
//  @param ctx
//
func (c *AdminCouponController) PostImport(ctx iris.Context) {
	var (
		giftId   int
		gift     *model.Gift
		codes    string
		codeList []string
		code     string
		sucCnt   int
		failCnt  int
		err      error
	)
	// 入参
	giftId = ctx.URLParamIntDefault("giftId", 0)
	if giftId < 1 {
		// 没有指定奖品id
		goto FAIL
	}
	// 根据giftId查询
	gift = service.G_giftService.Get(giftId, true)
	// 虚拟券 不同的码
	if gift == nil || gift.Type != 2 {
		goto FAIL
	}
	// request body
	codes = ctx.PostValue("codes")
	// 字符串分割
	codeList = strings.Split(codes, "\n")
	sucCnt = 0
	failCnt = 0
	// 遍历 入库 缓存
	for _, code = range codeList {
		code = strings.TrimSpace(code)
		if code != "" {
			// 入库
			if err = service.G_couponService.Create(&model.Coupon{
				GiftId:     giftId,
				Code:       code,
				GmtCreated: common.NowUnix(),
			}); err != nil {
				failCnt++
			} else {
				// 缓存
				if _, err = datasource.G_redis.Do("SADD", fmt.Sprintf("gift_code_%d", giftId), code); err != nil {
					failCnt++
				} else {
					sucCnt++
				}
			}
		}
	}
	response.Ok(ctx, response.CODE_OK, fmt.Sprintf("导入结果 成功%d条 失败%d条", sucCnt, failCnt))
	return
FAIL:
	response.Error(ctx, iris.StatusOK, response.CODE_FAILUR)
	return

}

//
//  GetDelete
//  @Description:
//                Delete http://localhost:8080/api/mini-prize/admin-coupon/?id=1
//  @receiver c
//  @param ctx
//
func (c *AdminCouponController) GetDelete(ctx iris.Context) {
	var (
		id  int
		err error
	)
	// 入参
	if id, err = ctx.URLParamInt("id"); err != nil {
		goto FAIL
	}
	// 删除
	if err = service.G_couponService.Delete(id); err != nil {
		goto FAIL
	}
	// 删除成功
	response.Ok(ctx, response.CODE_OK, "删除成功")
	return
FAIL:
	response.Error(ctx, iris.StatusOK, response.CODE_FAILUR)
	return

}

//
//  GetReset
//  @Description:
//                Get http://localhost:8080/api/mini-prize/admin-coupon/reset/?id=1
//  @receiver c
//  @param ctx
//
func (c *AdminCouponController) GetReset(ctx iris.Context) {
	var (
		id  int
		err error
	)
	// 入参
	if id, err = ctx.URLParamInt("id"); err != nil {
		goto FAIL
	}
	// 更新
	if err = service.G_couponService.Update(&model.Coupon{Id: id, Status: 0}, []string{"status"}); err != nil {
		goto FAIL
	}
	response.Ok(ctx, response.CODE_OK, "重置成功")
	return
FAIL:
	response.Error(ctx, iris.StatusOK, response.CODE_FAILUR)
	return
}

//
//  GetRecache
//  @Description: 重新整理优惠券的数据
//                Get http://localhost:8080/api/mini-prize/admin-coupon/recache/?id=1
//  @receiver c
//  @param ctx
//
func (c *AdminCouponController) GetRecache(ctx iris.Context) {
	var (
		id       int
		err      error
		sucCnt   int
		failCnt  int
		dataList []model.Coupon
		data     model.Coupon
		key      string
		tmpKey   string
		code     string
	)
	// 入参
	if id, err = ctx.URLParamInt("id"); err != nil || id < 1 {
		// 没有指定优惠券所属的奖品id
		goto FAIL
	}
	// 根据id查询数据库
	dataList = service.G_couponService.Search(id)
	if dataList == nil || len(dataList) <= 0 {
		goto FAIL
	}
	// redis中缓存的key值
	key = fmt.Sprintf("gift_code_%d", id)
	tmpKey = "tmp_" + key
	for _, data = range dataList {
		if data.Status == 0 {
			code = data.Code
			if _, err = datasource.G_redis.Do("SADD", tmpKey, code); err != nil {
				failCnt++
			} else {
				sucCnt++
			}
		}
	}
	if _, err = datasource.G_redis.Do("RENAME", tmpKey, key); err != nil {
		// XXX: 2021/11/27
	}
	response.Ok(ctx, response.CODE_OK, fmt.Sprintf("成功%d条 失败%d条", sucCnt, failCnt))
	return
FAIL:
	response.Error(ctx, iris.StatusOK, response.CODE_FAILUR)
	return
}
